#include "Model3DStorage.h"
#include "Model3D.h"
#include "BoundingBox.h"
#include "SharedConstants.h"

void Model3DStorage::AddModel(const std::string& i_type, std::shared_ptr<Model3D> i_model, const TVector3& i_size, bool i_need_shift)
  {
  if (m_models.count(i_type))
    {
    throw std::string("Adding existing model to Model3DStorage");
    }
  _FitModelSize(i_model, i_size);
  if (i_need_shift)
    _ParalelModelShift(i_model);
  m_models[i_type] = i_model;
  }

const Model3D& Model3DStorage::GetModel(const std::string& i_type) const
  {
  if (m_models.count(i_type))
    {
    return *m_models.find(i_type)->second;
    }
  throw std::string("Model of type " + i_type + " was'n found in Model3DStorage");
  }

void Model3DStorage::_FitModelSize(std::shared_ptr<Model3D> i_model, const TVector3& i_size)
  {
  // create bounding box
  BoundingBox model_box = CalculateBoundingBox(*i_model);

  // get scale coefficient
  double sz_x = model_box.m_max_x - model_box.m_min_x;
  double sz_y = model_box.m_max_y - model_box.m_min_y;
  double sz_z = model_box.m_max_z - model_box.m_min_z;

  double coef_x = i_size.X() / sz_x;
  double coef_y = i_size.Y() / sz_y;
  double coef_z = i_size.Z() / sz_z;

  TVector3 coef = TVector3(coef_x, coef_y, coef_z);

  // apply scale transform 
  i_model->ScaleTransform(coef);

  }

void Model3DStorage::_ParalelModelShift(std::shared_ptr<Model3D> i_model)
  {
  // creating bounding box
  BoundingBox model_box = CalculateBoundingBox(*i_model);

  // get shifting vector 
  double x_shift = GroundConstants::ORIGIN_X - (model_box.m_min_x + model_box.m_max_x) / 2;
  double y_shift = GroundConstants::ORIGIN_Y - (model_box.m_min_y + model_box.m_max_y) / 2;
  double z_shift = GroundConstants::ORIGIN_Z - model_box.m_min_z;
  
  TVector3 scaling_vector = TVector3(x_shift, y_shift, z_shift);

  //apply paralel shift
  i_model->ParalelShift(scaling_vector);
  }
